package lovedna.display.movieclip {
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	import lovedna.utils.BitmapDataUtil;


	/**
	 * @author hi
	 */
	[Event(name = "complete", type = "flash.events.Event")]
	public class MovieClip2Bitmaps extends EventDispatcher {
		private var _rect : Rectangle;
		private var _matrix : Matrix;
		private var _data : Object;
		private var _mc : MovieClip;
		private var _totalFrame : int;
		private var _frameRate : Number;
		private var _skipFrame : uint;
		private var _frameList : MovieClipFrameList;
		private var _checkbmd : Boolean;
		private var _crcdict : Dictionary;
		private var _async : Boolean;

		public function MovieClip2Bitmaps(data : Object = null) {
			_data = data;
			_matrix = new Matrix();
			_crcdict = new Dictionary();
			_async = true;
		}
		/*
		 * 设置异步或同步解析动画
		 */
		public function set async(value : Boolean) : void {
			_async = value;
		}
		/**
		 * 是否检测相同的位图数据
		 * 可能消耗时间长和不准确
		 */
		public function set checkbmd(checkbmd : Boolean) : void {
			_checkbmd = checkbmd;
		}

		public function release() : void {
			if(_mc){
				_mc.removeEventListener(Event.ENTER_FRAME, enterframe);
			}
			_rect = null;
			_matrix = null;
			_data = null;
			_mc = null;
			_crcdict = null;
			_frameList = null;
		}

		public function getMovieClip(value : MovieClip, frameRate : Number, skipFrame : uint = 1) : void {
			_mc = value;
			_totalFrame = _mc.totalFrames;
			_frameRate = frameRate;
			_skipFrame = skipFrame;
			_frameList = new MovieClipFrameList();
			if (_async) {
				_mc.addEventListener(Event.ENTER_FRAME, enterframe);
				enterframe(null);
				_mc.gotoAndPlay(1);
			} else {
				for (var i : int = 1; i <= _totalFrame; i++) {
					if (i % _skipFrame == 0) {
						_mc.gotoAndStop(i);
						addFrame();
					}
				}
				dispatchEvent(new Event(Event.COMPLETE));
				release();
			}
		}

		private function enterframe(event : Event) : void {
			var c : int = _mc.currentFrame;
			if (c % _skipFrame == 0) {
				addFrame();
			}
			if (c >= _totalFrame) {
				_mc.removeEventListener(Event.ENTER_FRAME, enterframe);
				dispatchEvent(new Event(Event.COMPLETE));
				release();
			}
		}

		private function addFrame() : void {
			_rect = _mc.getRect(_mc);
			var left : Number = Math.floor(_rect.left);
			var top : Number = Math.floor(_rect.top);
			var w : int = Math.ceil(_rect.width);
			var h : int = Math.ceil(_rect.height);
			if (w == 0) {
				w = 1;
			}
			if (h == 0) {
				h = 1;
			}
			var bmd : BitmapData = new BitmapData(w, h, true, 0);
			_matrix.tx = -left;
			_matrix.ty = -top;
			bmd.draw(_mc, _matrix);
			_rect = BitmapDataUtil.getOpaque(bmd);
			_rect.left = Math.floor(_rect.left);
			_rect.top = Math.floor(_rect.top);
			_rect.width = Math.ceil(_rect.width);
			_rect.height = Math.ceil(_rect.height);
			left += (_rect.left);
			top += (_rect.top);
			var newbmd : BitmapData;
			if (_rect.width == 0 || _rect.height == 0) {
			} else {
				newbmd = BitmapDataUtil.trim(bmd, _rect);
			}
			newbmd = check(newbmd);
			var framedata : MovieClipFrame = new MovieClipFrame(newbmd, 1000 / _frameRate);
			framedata.registrationX = -left;
			framedata.registrationY = -top;
			_frameList.addFrame(framedata);
			bmd.dispose();
			framedata = null;
			newbmd = null;
		}

		private function check(bmd : BitmapData) : BitmapData {
			if (!_checkbmd) return bmd;
			var len : int = _frameList.length;
			while (len--) {
				var last : MovieClipFrame = _frameList.getFrame(len);
				if (last) {
					var lastbmd : BitmapData = last.bitmapData;
					if (lastbmd) {
						if (lastbmd.compare(bmd) == 0) {
							return lastbmd;
						}
					}
				}
			}
			return bmd;
		}

		public function get data() : Object {
			return _data;
		}

		public function get frameList() : MovieClipFrameList {
			return _frameList.clone();
		}

	}
}
